package service

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"math/rand"
	"net/http"
	"strings"
	"sync"
	"time"
	"zy-api/curl"

	"github.com/gin-gonic/gin"
	ark "github.com/sashabaranov/go-openai"
)

// ------------------- 性格库 -------------------
var personalities = []string{
	// 积极型
	"乐观", "开朗", "热情", "果敢", "机智", "豪爽", "坚毅", "自信",
	"豁达", "阳光", "爽快", "勇敢", "干练", "坚定", "活泼", "率真",
	"直率", "坦诚", "细心", "稳重", "耐心", "真诚", "理智", "大方",
	"积极向上", "热心助人", "随遇而安", "勇往直前", "自律严格", "多才多艺",
	// 中性型
	"冷静", "谨慎", "淡定", "敏锐", "平和", "沉稳", "安静", "知性",
	"洒脱", "随和", "随性", "含蓄", "内敛", "低调", "不争不抢", "随心所欲",
	"处事圆滑", "善解人意", "沉着冷静", "随波逐流", "胸怀坦荡",
	// 消极型
	"孤僻", "固执", "悲观", "多疑", "冷漠", "犹豫", "敏感", "孤独",
	"倔强", "自卑", "胆小", "刻薄", "自闭", "消沉", "寡言", "怯懦",
	"优柔寡断", "多愁善感", "杞人忧天", "悲观消极", "患得患失", "情绪化",
	// 特殊型
	"古灵精怪", "天马行空", "想象丰富", "我行我素", "独立自主",
	"坚持己见", "直觉敏锐", "洞察入微", "温柔体贴", "豪情万丈",
	"桀骜不驯", "天真烂漫", "与世无争", "快人快语", "勇敢无畏",
	"不拘小节", "深谋远虑", "敢爱敢恨", "随性潇洒",
}

// ------------------- 五行种族库 -------------------
var races = map[string][]string{
	"金": {"金系·钢铁兽", "金系·银光鹰", "金系·铜角鹿", "金系·铜狮", "金系·银狼", "金系·金甲龟"},
	"木": {"木系·菜菜芽", "木系·青藤蛇", "木系·枫叶鹿", "木系·木灵狐", "木系·藤蔓兽", "木系·竹熊"},
	"水": {"水系·泡泡鱼", "水系·蓝鲸", "水系·海豚", "水系·冰龙", "水系·水精灵", "水系·涟漪豹"},
	"火": {"火系·霹雳火", "火系·红焰鸟", "火系·炎龙", "火系·火狐", "火系·烈焰狮", "火系·焰焰兔"},
	"土": {"土系·土狼", "土系·岩石龟", "土系·泥熊", "土系·土灵牛", "土系·沙蟹", "土系·岩鹰"},
}

// ------------------- 名字库 -------------------
var names = []string{
	"霹雳火", "糖糖布丁", "小丸子", "闪电豹", "绿叶精灵",
	"火焰兔", "海蓝宝", "小黑猫", "蓝莓酱", "糖果兔",
	"阿狸", "雪球", "小虎牙", "蜜糖猫", "闪光狼",
	"冰霜豹", "红宝石", "小鹿斑比", "桃子君", "彩虹鱼",
	"闪电鸟", "小熊维尼", "月光兔", "甜心豹", "蓝天鹰",
	"草莓熊", "星星猫", "火焰鸟", "小白兔", "小灰狼",
	"布丁熊", "阳光虎", "蓝狐", "雪豹王", "红焰虎",
	"小魔仙", "果冻猫", "火焰狮", "冰晶狐", "彩虹马",
	"小青蛙", "雪球狐", "蓝莓熊", "闪电狐", "蜜糖兔",
	"小熊猫", "火焰豹", "月光猫", "蓝焰龙", "小鹿鹿",
	"巧克力熊", "星光兔", "红焰鸟", "糖果虎", "冰霜狼",
	"小萌狐", "闪电豹", "蓝莓兔", "火焰狐", "小雪豹",
	"甜心猫", "小火龙", "月亮熊", "彩虹兔", "冰蓝豹",
	"小虎猫", "火焰兔", "蓝光狐", "雪白鹿", "红宝鸟",
	"小橘子", "闪光猫", "蜜糖豹", "蓝焰狐", "小狐狸",
	"雪球熊", "火焰鸟", "月光虎", "彩虹狐", "小雪狼",
	"布丁兔", "星光豹", "红焰狐", "冰蓝兔", "小萌豹",
	"巧克力兔", "闪电鸟", "蓝莓狐", "火焰豹", "小鹿狐",
	"小灰熊", "甜心兔", "月光豹", "彩虹狼", "冰霜狐",
	"小萌猫", "火焰狐", "蓝光豹", "雪白兔", "红宝狐",
	"小橙子", "闪光狼", "蜜糖兔", "蓝焰豹", "小狐狸",
	"雪球虎", "火焰兔", "月光狼", "彩虹豹", "小雪狐",
	"布丁猫", "星光狐", "红焰豹", "冰蓝狼", "小萌狐",
	"巧克力虎", "闪电狐", "蓝莓豹", "火焰兔", "小鹿豹",
	// 总共 100+ 个，可继续扩充到 200+
}

const key = "Z6TNr3uzLkMUJ86V1e9Ot53kX"
const yunshi = "https://api.yuanfenju.com/index.php/v1/Bazi/yunshi"
const hepan = "https://api.yuanfenju.com/index.php/v1/Bazi/hepan"

type Result[T any] struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data T      `json:"data"`
}

func StartControlServer() {
	router := gin.Default()
	// 注册控制接口
	router.GET("/zhongzu", ApiZhongZu())
	router.GET("/name", ApiName())
	router.GET("/xingge", ApiXingGe())
	router.POST("/yunshi", ApiYunShi())
	router.POST("/hepan", ApiHePan())
	router.POST("/wxLogin", ApiWxLogin)
	router.Run(":8001")
}

// AccessTokenResp 获取全局 access_token 的返回结构
type AccessTokenResp struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
	ErrCode     int    `json:"errcode"`
	ErrMsg      string `json:"errmsg"`
}

// WxPhoneResp 获取手机号接口返回结构
type WxPhoneResp struct {
	ErrCode   int    `json:"errcode"`
	ErrMsg    string `json:"errmsg"`
	PhoneInfo struct {
		PhoneNumber     string `json:"phoneNumber"`
		PurePhoneNumber string `json:"purePhoneNumber"`
		CountryCode     string `json:"countryCode"`
	} `json:"phone_info"`
}

func ApiWxLogin(c *gin.Context) {
	code := c.Query("code")
	// 1️⃣ 先获取全局 access_token
	token, err := getWxAccessToken()
	if err != nil {
		fmt.Println("获取 access_token 失败:", err)
		return
	}
	// 3️⃣ 获取手机号
	mobile, err := getWxUserPhone(token, code)
	fmt.Println(mobile)
	if err != nil {
		fmt.Println("获取手机号失败:", err)
		return
	}
}

// getWxAccessToken 获取全局 access_token
func getWxAccessToken() (string, error) {
	appid := "wx0bc64c6805b4d4d2"
	secret := "58c2da651dbe3e31adf8697b83d97db2"

	url := fmt.Sprintf(
		"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
		appid, secret,
	)

	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	var result AccessTokenResp
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return "", err
	}

	if result.ErrCode != 0 {
		return "", fmt.Errorf("wechat error: %d %s", result.ErrCode, result.ErrMsg)
	}
	return result.AccessToken, nil
}

// getWxUserPhone 获取微信手机号
func getWxUserPhone(accessToken, code string) (string, error) {
	url := fmt.Sprintf("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s", accessToken)

	body := map[string]string{"code": code}
	jsonBody, _ := json.Marshal(body)

	resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonBody))
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	data, _ := io.ReadAll(resp.Body)
	var result WxPhoneResp
	if err := json.Unmarshal(data, &result); err != nil {
		return "", err
	}

	if result.ErrCode != 0 {
		return "", fmt.Errorf("wechat api error: %d %s", result.ErrCode, result.ErrMsg)
	}

	return result.PhoneInfo.PhoneNumber, nil
}

type YunShi struct {
	Name        string `json:"name"`
	Sex         string `json:"sex"`
	Date        string `json:"date"`
	Time        string `json:"time"`
	Personality string `json:"personality"`
}

// /zhongzu 返回随机五行种族
func ApiZhongZu() gin.HandlerFunc {
	return func(c *gin.Context) {
		dateStr := c.Query("date")
		if dateStr == "" {
			c.JSON(http.StatusBadRequest, Result[string]{http.StatusBadRequest, "缺少日期参数", ""})
			return
		}
		date, err := time.Parse("2006-01-02", dateStr)
		if err != nil {
			c.JSON(http.StatusBadRequest, Result[string]{http.StatusBadRequest, "日期格式错误", ""})
			return
		}
		race := getRaceByDate(date)
		c.JSON(http.StatusOK, Result[string]{http.StatusOK, "获取成功", race})
	}
}

// /name 返回随机名字
func ApiName() gin.HandlerFunc {
	return func(c *gin.Context) {
		name := getRandomName()
		c.JSON(http.StatusOK, Result[string]{http.StatusOK, "获取成功", name})
	}
}

// /xingge 返回随机性格
func ApiXingGe() gin.HandlerFunc {
	return func(c *gin.Context) {
		personality := personalities[rand.Intn(len(personalities))]
		c.JSON(http.StatusOK, Result[string]{http.StatusOK, "获取成功", personality})
	}
}

// ------------------- 根据日期生成五行种族 -------------------
func getRaceByDate(date time.Time) string {
	year := date.Year() % 10
	month := int(date.Month())

	switch {
	case year == 0 || year == 1:
		return races["水"][rand.Intn(len(races["水"]))]
	case month == 3 || month == 4:
		return races["木"][rand.Intn(len(races["木"]))]
	case month == 5 || month == 6:
		return races["火"][rand.Intn(len(races["火"]))]
	case month == 7 || month == 8:
		return races["土"][rand.Intn(len(races["土"]))]
	default:
		return races["金"][rand.Intn(len(races["金"]))]
	}
}

// ------------------- 随机名字 -------------------
func getRandomName() string {
	return names[rand.Intn(len(names))]
}

func ApiYunShi() gin.HandlerFunc {
	return func(c *gin.Context) {
		var req YunShi
		if err := c.ShouldBindJSON(&req); err != nil {
			c.JSON(http.StatusBadRequest, Result[string]{http.StatusBadRequest, "参数解析失败", ""})
			return
		}
		// 解析日期
		date, err := time.Parse("2006-01-02", req.Date)
		if err != nil {
			c.JSON(http.StatusBadRequest, Result[string]{http.StatusBadRequest, "日期格式错误", ""})
			return
		}

		// 解析时间（时:分）
		t, err := time.Parse("15:04", req.Time)
		if err != nil {
			c.JSON(http.StatusBadRequest, Result[string]{http.StatusBadRequest, "时间格式错误", ""})
			return
		}

		// 获取年月日
		year, month, day := date.Date()
		// 获取时分
		hour, minute, _ := t.Clock()
		body := map[string]any{
			"api_key": key,
			"name":    req.Name,
			"sex":     req.Sex,
			"type":    "1",
			"year":    year,
			"month":   month,
			"day":     day,
			"hours":   hour,
			"minute":  minute,
		}
		jsonStr, _ := json.Marshal(body)
		fmt.Println(string(jsonStr))
		client := curl.DefaultClient()
		param := &curl.RequestParam{
			Header: map[string]interface{}{"Content-Type": "application/json"},
			Url:    yunshi,
			Method: "POST",
			Body:   string(jsonStr),
		}
		resp, err := client.Send(param)
		fmt.Println(resp)
		template := `根据性格 {personality} 输出 JSON，务必严格按性格风格书写，语气必须完全体现该性格特点：
					{
						"overview": "用30~50字描述今日运势，要体现{personality}的口吻和思维方式，旁白风格",
						"score":"综合，只显示分数",
					  	"health": "健康，只显示分数",
					  	"career": "事业，只显示分数",
					  	"love": "爱情，只显示分数",
					  	"wealth": "财运，只显示分数",
					  	"suitable": "今日适宜事项+简短解析（≤10字），用{personality}的语气，可带emoji",
					  	"avoid": "今日忌讳事项+简短解析（≤10字），用{personality}的语气，可带emoji",
					  	"summary": "总结今日行动建议+简短解析（≤10字），用{personality}的语气，可带emoji"
					}
					只输出 JSON，不要加其他文字，不允许偏离性格风格。`
		c.JSON(http.StatusOK, Result[string]{http.StatusOK, "成功", getResult(resp, req.Personality, template)})
	}
}

type HePan struct {
	MaleName    string `json:"maleName"`
	MaleDate    string `json:"maleDate"`
	MaleTime    string `json:"maleTime"`
	FemaleName  string `json:"femaleName"`
	FemaleDate  string `json:"femaleDate"`
	FemaleTime  string `json:"femaleTime"`
	Personality string `json:"personality"`
}

type HePanUser struct {
	Key         string `json:"key"`
	Name        string `json:"name"`
	Type        string `json:"type"`
	Date        string `json:"date"`
	Time        string `json:"time"`
	Personality string `json:"personality"`
}

type waitGroup struct {
	mu    sync.Mutex
	users []HePanUser
	ch    chan struct{} // 通知通道
}

var (
	hePanCache = sync.Map{} // key -> *waitGroup
)

func ApiHePan() gin.HandlerFunc {
	return func(c *gin.Context) {
		var req HePanUser
		if err := c.ShouldBindJSON(&req); err != nil {
			c.JSON(http.StatusBadRequest, Result[string]{http.StatusBadRequest, "参数解析失败", ""})
			return
		}

		if _, err := time.Parse("2006-01-02", req.Date); err != nil {
			c.JSON(http.StatusBadRequest, Result[string]{http.StatusBadRequest, "日期格式错误", ""})
			return
		}
		if _, err := time.Parse("15:04", req.Time); err != nil {
			c.JSON(http.StatusBadRequest, Result[string]{http.StatusBadRequest, "时间格式错误", ""})
			return
		}

		val, _ := hePanCache.LoadOrStore(req.Key, &waitGroup{
			users: []HePanUser{},
			ch:    make(chan struct{}),
		})
		wg := val.(*waitGroup)

		wg.mu.Lock()
		wg.users = append(wg.users, req)
		if len(wg.users) > 2 {
			wg.users = wg.users[len(wg.users)-2:]
		}
		usersCount := len(wg.users)
		wg.mu.Unlock()

		if usersCount == 2 {
			// 非阻塞安全地关闭通道，仅关闭一次
			select {
			case <-wg.ch:
				// already closed
			default:
				close(wg.ch)
			}
		} else {
			select {
			case <-wg.ch:
				// got notified
			case <-time.After(30 * time.Second):
				c.JSON(http.StatusOK, Result[string]{http.StatusOK, "等待超时，请稍后再试", ""})
				return
			}
		}

		wg.mu.Lock()
		if len(wg.users) != 2 {
			wg.mu.Unlock()
			c.JSON(http.StatusOK, Result[string]{http.StatusOK, "人数不足，请稍后重试", ""})
			return
		}
		male := wg.users[0]
		female := wg.users[1]
		wg.mu.Unlock()

		maleDate, _ := time.Parse("2006-01-02", male.Date)
		maleT, _ := time.Parse("15:04", male.Time)
		maleYear, maleMonth, maleDay := maleDate.Date()
		maleHour, maleMinute, _ := maleT.Clock()

		femaleDate, _ := time.Parse("2006-01-02", female.Date)
		femaleT, _ := time.Parse("15:04", female.Time)
		femaleYear, femaleMonth, femaleDay := femaleDate.Date()
		femaleHour, femaleMinute, _ := femaleT.Clock()

		body := map[string]any{
			"api_key":       key,
			"male_name":     male.Name,
			"male_type":     male.Type,
			"male_year":     maleYear,
			"male_month":    maleMonth,
			"male_day":      maleDay,
			"male_hours":    maleHour,
			"male_minute":   maleMinute,
			"female_name":   female.Name,
			"female_type":   female.Type,
			"female_year":   femaleYear,
			"female_month":  femaleMonth,
			"female_day":    femaleDay,
			"female_hours":  femaleHour,
			"female_minute": femaleMinute,
		}
		jsonStr, _ := json.Marshal(body)

		client := curl.DefaultClient()
		param := &curl.RequestParam{
			Header: map[string]interface{}{"Content-Type": "application/json"},
			Url:    hepan,
			Method: "POST",
			Body:   string(jsonStr),
		}
		resp, err := client.Send(param)
		if err != nil {
			c.JSON(http.StatusInternalServerError, Result[string]{http.StatusInternalServerError, "合盘接口请求失败", ""})
			return
		}
		template := `根据性格 {personality} 输出 JSON，务必严格按性格风格书写，语气必须完全体现该性格特点：
				{
					"otherName":"对方的名称",
					"otherDate":"对方出生日期 yyyy-mm-dd格式",
					"otherTime":"对方出生时间 hh:mm格式",
					"overall": "整体合盘结论，用50~80字总结，用{personality}的语气，可带emoji",
					"score":"综合，只显示分数",
					"love": "爱情匹配度，只输出分数(0-100)",
					"career": "事业匹配度，只输出分数(0-100)",
					"friendship": "友情匹配度，只输出分数(0-100)",
					"marriage": "婚姻稳定度，只输出分数(0-100)",
					"advice": "给双方的关系建议，≤20字，用{personality}的语气，可带emoji"
				}
				只输出 JSON，不要加其他文字，不允许偏离性格风格。`

		// 返回结果
		c.JSON(http.StatusOK, Result[string]{http.StatusOK, "成功", getResult(resp, male.Personality+female.Personality, template)})

		//清理缓存
		//hePanCache.Delete(req.Key)
		return
	}
}

func getResult(body string, personality string, template string) string {
	config := ark.DefaultConfig("a2526f5b-d3ef-4925-bed1-52035338323d")
	config.BaseURL = "https://ark.cn-beijing.volces.com/api/v3"
	client := ark.NewClientWithConfig(config)
	fmt.Println("----- 模型封装 -----")

	// 替换 {personality} 为传入参数
	prompt := strings.ReplaceAll(template, "{personality}", personality)
	req := ark.ChatCompletionRequest{
		Model: "doubao-seed-1-6-flash-250715",
		Messages: []ark.ChatCompletionMessage{
			{
				Role: ark.ChatMessageRoleUser,
				MultiContent: []ark.ChatMessagePart{
					{
						Type: ark.ChatMessagePartTypeText,
						Text: body,
					},
					{
						Type: ark.ChatMessagePartTypeText,
						Text: prompt,
					},
				},
			},
		},
	}
	resp, err := client.CreateChatCompletion(context.Background(), req)
	if err != nil {
		fmt.Printf("ChatCompletion error: %v", err)
		return ""
	}
	fmt.Println(resp.Choices[0].Message.Content)
	return resp.Choices[0].Message.Content
}
